//
// Created by mio on 25-4-11.
//

#include "Timer.h"

TimerId TimerQueue::AddTimer(const TimerEvent& event, uint32_t msec)
{
    // 获取当前时间作为计算首次超时的基准
    int64_t time_point = GetTimeNow();
    TimerId timerid = ++last_timer_id_;

    auto timer = std::make_shared<Timer>(event, msec);
    // 计算并设置该定时器的首次超时时间点
    timer->SetNextTimeout(time_point);
    // 将 TimerId 和 Timer 指针存入 timers_ map，用于通过 ID 快速查找
    timers_.emplace(timerid, timer);
    //    将 <超时时间点, TimerId> 和 Timer 指针存入 events_ map，用于按时间排序和触发
    //    使用 emplace 可以原地构造 pair，可能效率稍高
    events_.emplace(std::pair<int64_t, TimerId>(time_point, timerid), timer);
    return timerid;
}

void TimerQueue::RemoveTimer(TimerId timerid)
{
    auto it = timers_.find(timerid);
    if (it != timers_.end())
    {
        // 获取该 Timer 的超时时间点，用于构造在 events_ map 中的 key
        int64_t timeout = it->second->GetNextTimeout();
        //    从 events_ map 中移除对应的条目
        //    需要构造 pair<int64_t, TimerId> 作为 key
        events_.erase(std::pair<int64_t, TimerId>(timeout, timerid));
        timers_.erase(timerid);
    }
}

void TimerQueue::HandleTimerEvent()
{
    if (!timers_.empty())
    {
        // 获取当前时间点
        int64_t timepoint = GetTimeNow();
        //    循环处理所有已到期的定时器
        //    events_.begin() 指向 map 中 key 最小（即超时时间最早）的元素
        //    只要最早的定时器超时时间 <= 当前时间，就处理它
        while (!timers_.empty() && !events_.empty() && events_.begin()->first.first <= timepoint)
        {
            // 获取到期定时器的 ID
            TimerId timerId = events_.begin()->first.second;
            // 执行该定时器的回调函数，并获取返回值 (true=重复, false=单次)
            if (events_.begin()->first.second)
            {
                bool flag = false;
                if (events_.begin()->second->eventCallback_)
                    flag = events_.begin()->second->eventCallback_();
                if (flag) // 如果回调返回 true，表示是周期性定时器
                {
                    // 重新计算并设置下一次超时时间点，基准是当前时间 timepoint
                    events_.begin()->second->SetNextTimeout(timepoint);
                    // 从 events_ map 中移除当前条目 (因为超时时间变了)
                    // 先用 move 获取 shared_ptr 的所有权（可选但清晰）
                    auto timePtr = std::move(events_.begin()->second);
                    events_.erase(events_.begin());
                    // 将更新了超时时间点的 Timer 重新插入 events_ map
                    // map 会自动将其放到按新时间排序的正确位置
                    events_.emplace(std::pair<int64_t, TimerId>(timePtr->GetNextTimeout(), timerId), timePtr);
                }
                else // 如果回调返回 false，表示是单次定时器或不再需要重复
                {
                    // 从 events_ map 中移除该定时器
                    events_.erase(events_.begin());
                    // 从 timers_ map 中也移除该定时器 (根据 ID)
                    timers_.erase(timerId);
                }
            }
        }
    }
}

int64_t TimerQueue::GetTimeRemaining()
{
    std::lock_guard<std::mutex> lock(mtx_);
    if (timers_.empty()) return -1;
    int64_t msec = events_.begin()->first.first - GetTimeNow();
    if (msec < 0) msec = 0;
    return msec;
}

int64_t TimerQueue::GetTimeNow()
{
    // 获取当前稳定时钟的时间点
    auto time_point = std::chrono::steady_clock::now();
    // 计算从时钟纪元开始到当前时间点的持续时间
    auto duration_since_epoch = time_point.time_since_epoch();
    // 将该持续时间转换为毫秒单位
    auto ms_duration = std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch);
    // 获取毫秒数的计数值 (int64_t) 并返回
    return ms_duration.count();

    // return std::chrono::duration_cast<std::chrono::milliseconds>(time_point.time_since_epoch()).count();
}
